from datetime import datetime, timedelta  # 导入日期时间和时间间隔类型
from jose import JWTError, jwt  # 导入JWT库，用于令牌的创建和验证
from passlib.context import CryptContext  # 导入密码哈希上下文
from typing import Optional  # 导入Optional类型
from fastapi import Depends, HTTPException, status  # 导入FastAPI依赖、异常和状态码
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials  # 导入HTTP Bearer认证
from sqlalchemy.orm import Session  # 导入SQLAlchemy会话

from app.schemas.user import TokenData  # 导入令牌数据模式
from app.db_models.user import User  # 导入用户模型
from app.database import get_db  # 导入数据库依赖

# 配置
SECRET_KEY = "IVIDS"  # JWT密钥，在生产环境中应该使用环境变量
ALGORITHM = "HS256"  # JWT加密算法
ACCESS_TOKEN_EXPIRE_MINUTES = 30  # 访问令牌过期时间（分钟）

# 密码哈希
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")  # 使用bcrypt算法进行密码哈希

# Token工具
security = HTTPBearer()  # 使用HTTP Bearer认证


def verify_password(plain_password, hashed_password):
    """验证密码
    
    比较明文密码和哈希密码是否匹配
    
    Args:
        plain_password: 明文密码
        hashed_password: 哈希后的密码
        
    Returns:
        bool: 密码是否匹配
    """
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    """获取密码哈希
    
    对明文密码进行哈希处理
    
    Args:
        password: 明文密码
        
    Returns:
        str: 哈希后的密码
    """
    return pwd_context.hash(password)


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    """创建访问令牌
    
    根据提供的数据创建JWT令牌
    
    Args:
        data: 要编码到令牌中的数据
        expires_delta: 过期时间间隔，None则使用默认值
        
    Returns:
        str: 编码后的JWT令牌
    """
    to_encode = data.copy()
    expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security),
    db: Session = Depends(get_db)
):
    """获取当前用户
    
    根据令牌获取当前认证的用户
    
    Args:
        credentials: HTTP认证凭据，通过依赖注入获取
        db: 数据库会话，通过依赖注入获取
        
    Returns:
        User: 当前用户对象
        
    Raises:
        HTTPException: 认证失败时抛出401异常
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="认证失败",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        token = credentials.credentials
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except (JWTError, Exception):
        raise credentials_exception
    
    user = db.query(User).filter(User.username == token_data.username).first()
    if user is None:
        raise credentials_exception
    return user